/* ***** BEGIN LICENSE BLOCK *****
 *   Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 * 
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is sudoku.
 *
 * The Initial Developer of the Original Code is
 * Petr Blahoš.
 * Portions created by the Initial Developer are Copyright (C) 2008
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 * 
 * ***** END LICENSE BLOCK ***** */

var consoleService = Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService);
function LOG(msg) {
	consoleService.logStringMessage(msg);
}
function DUMP_MEMBERS(o) {
	var s = "" + o + " members:";
	for (var i in o) {
		s+= i + ",";
	}
	LOG(s);
}

/****** define uF */
Components.utils.import("resource://gre/modules/Microformats.js");
function board(node, validate) {
	if (node) {
		Microformats.parser.newMicroformat(this, node, "board", validate);
	}
}
board.prototype.isValid = function() {
	return 81==this.cell.length;
}
board.prototype.toString = function() {
	var out = "";
	for (var i = 0;i<81;i++) {
		var x = this.cell[i].charAt(0);
		if (1==x.length && x>="1" && x<="9")	out+= x;
		else					out+= '0';
	}
	return out;
}
var format_definition = {
	mfVersion: 0.8,
	mfObject: board,
	className: "board",
	properties: {
		"cell": {
			plural: true
		}
	}
};
Microformats.add("board", format_definition);
/****** end uF definition */

var dissector = {
init: function() {
	// installs an on-load hook.
	Components.utils.import("resource://sudoku/griddb.jsm");

	this.strings = document.getElementById("sudoku-strings");
	try{
		var appcontent = document.getElementById("appcontent");   // browser
		if(appcontent){
			appcontent.addEventListener("DOMContentLoaded", this.onPageLoad, true);
		}
		dissector.browser = document.getElementById("content");
	}catch(e){}
},
onPageLoad: function(aEvent) {
	if ("chrome:"==aEvent.target.baseURI.substring(0, 7))	return ;
	if ("about:"==aEvent.target.baseURI.substring(0, 6))	return ;
	var doc = aEvent.target;
	setTimeout(function() {
		dissector.detect(doc, doc.baseURI);
	}, 1500);
},
detect: function(doc, uri) {
	var u = Microformats.get("board", doc.body);
	if (undefined!=u) {
		for (var i = 0;i<u.length;i++) {
			LOG("uF:" + u[i]);
			if (u[i].isValid()) {
				dissector.notify(doc, u[i].toString());
				return ;
			}
		}
	}
	if (	null!=doc.getElementById("sudokutable") &&
		null!=doc.getElementById("T0") && null!=doc.getElementById("T80")) {
		LOG("D1: maybe type 1");
		if (dissector.grab_type1(doc, uri)) {
			return ;
		}
	}
	if (	null!=doc.getElementById("f00") && null!=doc.getElementById("f88")) {
		LOG("D1: maybe type 2");
		if (dissector.grab_type2(doc, uri, "f")) {
			return ;
		}
	}
	if (	null!=doc.getElementById("inpt00") && null!=doc.getElementById("inpt88")) {
		LOG("D1: maybe type 2");
		if (dissector.grab_type2(doc, uri, "inpt")) {
			return ;
		}
	}
	if (	null!=doc.getElementById("f11") && null!=doc.getElementById("f99")) {
		LOG("D1: maybe type 3 - f");
		if (dissector.grab_type3(doc, uri, 'f')) {
			return ;
		}
	}
	if (	null!=doc.getElementById("c11") && null!=doc.getElementById("c99")) {
		LOG("D1: maybe type 3 - c");
		if (dissector.grab_type3(doc, uri, 'c')) {
			return ;
		}
	}
},
notify: function(doc, grid) {
	var notificationBox = this.browser.getNotificationBox(this.browser.getBrowserForDocument(doc.defaultView.document));
	// Remove existing notifications. Notifications get removed
	// automatically onclick and on page navigation, but we need to remove
	// them ourselves in the case of reload, or they stack up.
	for (var i = 0, child; child = notificationBox.childNodes[i]; i++) {
		if (child.getAttribute("value") == "grid-fromweb") {
			notificationBox.removeNotification(child);
		}
	}

	if (griddb.has_grid(grid)) {
		var notification = notificationBox.appendNotification(
			this.strings.getString('knownpuzzlefound.label'),
			"grid-fromweb",
			"",	// icon
			notificationBox.PRIORITY_WARNING_MEDIUM,
			[
			{ label: this.strings.getString('play.btn'),
			 accessKey: "P",
			 popup: null,
			 callback: function(){ dissector.run(doc, grid); } }
			 ]);
	} else {
		var notification = notificationBox.appendNotification(
			this.strings.getString('puzzlefound.label'),
			"grid-fromweb",
			"",	// icon
			notificationBox.PRIORITY_WARNING_MEDIUM,
			[
			{ label: this.strings.getString('play.btn'),
			 accessKey: "P",
			 popup: null,
			 callback: function(){ dissector.run(doc, grid); } },
			{ label: this.strings.getString('save.btn'),
			 accessKey: "S",
			 popup: null,
			 callback: function(){ dissector.save(grid); } }
			 ]);
	}
},
run: function(doc, grid) {
	//doc.defaultView.location.href = "chrome://sudoku/content/grid.xul?p=" + grid;
	dissector.browser.selectedTab = dissector.browser.addTab("chrome://sudoku/content/grid.xul?p=" + grid);
},
save: function(grid) {
	griddb.introduce(grid, null);
},
grab_type2: function(doc, uri, letter) {
	var r, c;
	var out = "";
	for (r = 0;r<9;r++) {
		for (c = 0;c<9;c++) {
			var id = doc.getElementById(letter + c + r);
			if (null==id) {
				return false;	// not this type.
			}
			if (""==id.value) {
				out+= "0";
			} else {
				var n = id.value.charCodeAt(0)-48;
				out+= n;
			}
		}
	}
	LOG("N:" + out);
	dissector.notify(doc, out);
	return true;
},
grab_type3: function(doc, uri, letter) {
	var r, c;
	var out = "";
	for (r = 1;r<10;r++) {
		for (c = 1;c<10;c++) {
			var id = doc.getElementById(letter + r + c);
			if (null==id) {
				return false;	// not this type.
			}
			if (""==id.value) {
				out+= "_";
			} else {
				var n = id.value.charCodeAt(0)-48;
				out+= n;
			}
		}
	}
	LOG("N:" + out);
	dissector.notify(doc, out);
	return true;
},
grab_type1: function(doc, uri) {
	var r, c, i = 0;
	var out = "";
	try {
		for (r = 0;r<9;r++) {
			for (c = 0;c<9;c++) {
				var id = doc.getElementById("T"+i);
				id = id.childNodes[0];
				if (1==id.nodeType && "B"==id.nodeName) {
					out+= id.innerHTML;
				} else {
					out+= '_';
				}
				i+= 1;
			}
		}
	} catch(e) {
		return false;
	}
	LOG("N:" + out);
	dissector.notify(doc, out);
},
/*grab_type4: function(doc, uri) {
	var r, c, i = 1;
	var out = "";
	for (r = 0;r<9;r++) {
		for (c = 0;c<9;c++) {
			var id = doc.getElementById("c" + i);
			if (null==id) {
				return False;	// not this type.
			}
			LOG("value: [" + r + "," + c + "] = " + id.value);
			i+= 1;
		}
	}
},*/
__sentinel: 0
};

window.addEventListener("load", function() { dissector.init(); }, false);

